package org.yunai.yfserver.message.schedule;

import org.yunai.yfserver.message.IMessage;

import java.util.concurrent.ScheduledFuture;

/**
 * 系统内部定时执行消息
 * User: yunai
 * Date: 13-3-27
 * Time: 下午4:51
 */
public abstract class ScheduledMessage implements IMessage {

    // ==================== 消息状态 ====================
    /**
     * 消息处于已经初始化状态
     */
    public static final int STATE_INITIALIZED = 0;
    /**
     * 消息处于等待状态，可以被取消
     */
    public static final int STATE_WAITING = 1;
    /**
     * 消息在消息队列中，可以被取消
     */
    public static final int STATE_IN_QUEUE = 2;
    /**
     * 消息处于取消状态
     */
    public static final int STATE_CANCELED = 3;
    /**
     * 消息处于正在执行状态
     */
    public static final int STATE_EXECUTING = 4;
    /**
     * 消息处于执行完毕状态
     */
    public static final int STATE_DONE = 5;

    private ScheduledFuture<?> future;
    /**
     * 消息状态，任何操作该变量都需要sync
     */
    private int state;
    /**
     * 消息创建时间
     */
    private final long createTimestamp;
    /**
     * 消息定时触发时间
     */
    private long triggerTimestamp;

    protected ScheduledMessage(long createTimestamp) {
        setState(STATE_INITIALIZED);
        this.createTimestamp = createTimestamp;
    }

    public long getCreateTimestamp() {
        return createTimestamp;
    }

    public long getTriggerTimestamp() {
        return triggerTimestamp;
    }

    public void setTriggerTimestamp(long triggerTimestamp) {
        this.triggerTimestamp = triggerTimestamp;
    }

    public synchronized boolean isCanceled() {
        return state == STATE_CANCELED;
    }

    public synchronized void setState(int state) {
        this.state = state;
    }

    public ScheduledFuture<?> getFuture() {
        return future;
    }

    public void setFuture(ScheduledFuture<?> future) {
        this.future = future;
    }

    public synchronized void cancel() {
        switch (state) {
            case STATE_WAITING:
                if (future != null) {
                    future.cancel(false);
                }
                setState(STATE_CANCELED);
                break;
            case STATE_IN_QUEUE:
                setState(STATE_CANCELED);
                break;
        }
    }
}
